"""
Documentation Generator for GSM Extensions

This module provides automated documentation generation from extension configurations,
schemas, and metadata. It supports multiple output formats and integrates with the
extension system to provide comprehensive documentation.
"""

import json
import yaml
from pathlib import Path
from typing import Dict, List, Any, Optional, Union, Set, Tuple
from dataclasses import dataclass, field
from datetime import datetime
import re
from collections import defaultdict

from .schema_validator import SchemaValidator, ValidationResult
from .migration_tools import PythonExtensionAnalyzer, ExtensionAnalysis


@dataclass
class DocumentationSection:
    """Represents a section in the generated documentation."""
    title: str
    content: str
    level: int = 1
    subsections: List['DocumentationSection'] = field(default_factory=list)
    
    def to_markdown(self, base_level: int = 0) -> str:
        """Convert section to markdown format."""
        level = base_level + self.level
        header = '#' * level + ' ' + self.title + '\n\n'
        content = self.content + '\n\n'
        
        subsections = ''
        for subsection in self.subsections:
            subsections += subsection.to_markdown(level) + '\n'
        
        return header + content + subsections


@dataclass
class ExtensionDocumentation:
    """Complete documentation for an extension."""
    name: str
    version: str
    description: str
    sections: List[DocumentationSection] = field(default_factory=list)
    metadata: Dict[str, Any] = field(default_factory=dict)
    
    def to_markdown(self) -> str:
        """Generate complete markdown documentation."""
        doc = f"# {self.name} Extension\n\n"
        doc += f"**Version:** {self.version}\n\n"
        doc += f"{self.description}\n\n"
        
        if self.metadata.get('generated_at'):
            doc += f"*Generated on {self.metadata['generated_at']}*\n\n"
        
        for section in self.sections:
            doc += section.to_markdown() + '\n'
        
        return doc


class ConfigurationDocumentationGenerator:
    """Generates documentation from configuration schemas and data."""
    
    def __init__(self, schema_validator: Optional[SchemaValidator] = None):
        self.validator = schema_validator or SchemaValidator()
        self.type_descriptions = {
            'string': 'Text value',
            'integer': 'Whole number',
            'number': 'Numeric value',
            'boolean': 'True/false value',
            'array': 'List of values',
            'object': 'Configuration object'
        }
    
    def generate_schema_documentation(self, schema: Dict[str, Any], 
                                    title: str = "Configuration Schema") -> DocumentationSection:
        """Generate documentation from a JSON schema."""
        content = "This section describes the configuration options available.\n\n"
        
        section = DocumentationSection(
            title=title,
            content=content,
            level=2
        )
        
        if 'properties' in schema:
            section.subsections.append(
                self._generate_properties_documentation(schema['properties'], schema.get('required', []))
            )
        
        return section
    
    def _generate_properties_documentation(self, properties: Dict[str, Any], 
                                         required: List[str]) -> DocumentationSection:
        """Generate documentation for schema properties."""
        content = "| Property | Type | Required | Description | Default |\n"
        content += "|----------|------|----------|-------------|--------|\n"
        
        for prop_name, prop_schema in properties.items():
            prop_type = self._get_property_type(prop_schema)
            is_required = "Yes" if prop_name in required else "No"
            description = prop_schema.get('description', 'No description available')
            default = self._format_default_value(prop_schema.get('default'))
            
            # Handle enum values
            if 'enum' in prop_schema:
                enum_values = ', '.join(f"`{v}`" for v in prop_schema['enum'])
                description += f" (Options: {enum_values})"
            
            content += f"| `{prop_name}` | {prop_type} | {is_required} | {description} | {default} |\n"
        
        return DocumentationSection(
            title="Configuration Properties",
            content=content,
            level=3
        )
    
    def _get_property_type(self, prop_schema: Dict[str, Any]) -> str:
        """Get human-readable type description."""
        prop_type = prop_schema.get('type', 'unknown')
        
        if prop_type == 'array':
            if 'items' in prop_schema:
                item_type = prop_schema['items'].get('type', 'unknown')
                return f"Array of {item_type}"
            return "Array"
        
        return self.type_descriptions.get(prop_type, prop_type)
    
    def _format_default_value(self, default: Any) -> str:
        """Format default value for display."""
        if default is None:
            return "None"
        if isinstance(default, str):
            return f"`{default}`"
        return str(default)


class ExtensionDocumentationGenerator:
    """Main documentation generator for extensions."""
    
    def __init__(self, base_path: Optional[Path] = None):
        self.base_path = base_path or Path.cwd()
        self.schema_validator = SchemaValidator()
        self.config_doc_generator = ConfigurationDocumentationGenerator(self.schema_validator)
        self.python_analyzer = PythonExtensionAnalyzer()
    
    def generate_extension_documentation(self, extension_path: Path, 
                                       output_format: str = 'markdown') -> ExtensionDocumentation:
        """Generate comprehensive documentation for an extension."""
        extension_name = extension_path.name
        
        # Load extension metadata
        metadata = self._load_extension_metadata(extension_path)
        config_schema = self._load_extension_schema(extension_path)
        
        # Create base documentation
        doc = ExtensionDocumentation(
            name=metadata.get('name', extension_name),
            version=metadata.get('version', '1.0.0'),
            description=metadata.get('description', 'Extension for GSM solver management'),
            metadata={'generated_at': datetime.now().isoformat()}
        )
        
        # Generate sections
        doc.sections = self._generate_documentation_sections(
            extension_path, metadata, config_schema
        )
        
        return doc
    
    def _load_extension_metadata(self, extension_path: Path) -> Dict[str, Any]:
        """Load extension metadata from extension.json."""
        metadata_file = extension_path / 'extension.json'
        if metadata_file.exists():
            with open(metadata_file, 'r') as f:
                return json.load(f)
        
        # Try to extract from Python extension
        python_analysis = self.python_analyzer.analyze_extension(extension_path)
        if python_analysis:
            return {
                'name': python_analysis.name,
                'version': python_analysis.version,
                'description': python_analysis.description,
                'frameworks': python_analysis.frameworks,
                'capabilities': python_analysis.capabilities
            }
        
        return {}
    
    def _load_extension_schema(self, extension_path: Path) -> Optional[Dict[str, Any]]:
        """Load configuration schema for the extension."""
        schema_file = extension_path / 'config_schema.json'
        if schema_file.exists():
            with open(schema_file, 'r') as f:
                return json.load(f)
        return None
    
    def _generate_documentation_sections(self, extension_path: Path, 
                                       metadata: Dict[str, Any], 
                                       schema: Optional[Dict[str, Any]]) -> List[DocumentationSection]:
        """Generate all documentation sections for an extension."""
        sections = []
        
        # Overview section
        sections.append(self._generate_overview_section(metadata))
        
        # Installation section
        sections.append(self._generate_installation_section(extension_path))
        
        # Configuration section
        if schema:
            sections.append(
                self.config_doc_generator.generate_schema_documentation(schema, "Configuration")
            )
        
        # Usage examples section
        sections.append(self._generate_usage_section(extension_path, metadata))
        
        # Commands section
        sections.append(self._generate_commands_section(extension_path))
        
        # Files section
        sections.append(self._generate_files_section(extension_path))
        
        return sections
    
    def _generate_overview_section(self, metadata: Dict[str, Any]) -> DocumentationSection:
        """Generate overview section with extension details."""
        content = ""
        
        if 'frameworks' in metadata:
            frameworks = ', '.join(metadata['frameworks'])
            content += f"**Supported Frameworks:** {frameworks}\n\n"
        
        if 'capabilities' in metadata:
            content += "**Capabilities:**\n"
            for capability in metadata['capabilities']:
                content += f"- {capability}\n"
            content += "\n"
        
        if 'requirements' in metadata:
            content += "**Requirements:**\n"
            for req in metadata['requirements']:
                content += f"- {req}\n"
            content += "\n"
        
        return DocumentationSection(
            title="Overview",
            content=content,
            level=2
        )
    
    def _generate_installation_section(self, extension_path: Path) -> DocumentationSection:
        """Generate installation instructions."""
        content = f"To use this extension, ensure it's placed in the plugins directory:\n\n"
        content += f"```bash\n"
        content += f"# Copy extension to plugins directory\n"
        content += f"cp -r {extension_path.name}/ /path/to/gsm/plugins/\n\n"
        content += f"# The extension will be automatically discovered by GSM\n"
        content += f"gsm list-extensions\n"
        content += f"```\n\n"
        
        # Check for requirements file
        requirements_file = extension_path / 'requirements.txt'
        if requirements_file.exists():
            content += "### Dependencies\n\n"
            content += "Install required dependencies:\n\n"
            content += "```bash\n"
            content += f"pip install -r {extension_path.name}/requirements.txt\n"
            content += "```\n\n"
        
        return DocumentationSection(
            title="Installation",
            content=content,
            level=2
        )
    
    def _generate_usage_section(self, extension_path: Path, 
                              metadata: Dict[str, Any]) -> DocumentationSection:
        """Generate usage examples section."""
        content = "This section provides examples of how to use the extension.\n\n"
        
        # Look for example configuration files
        example_files = list(extension_path.glob('examples/*.xml')) + \
                       list(extension_path.glob('examples/*.yaml')) + \
                       list(extension_path.glob('example*.xml')) + \
                       list(extension_path.glob('example*.yaml'))
        
        if example_files:
            content += "### Example Configurations\n\n"
            for example_file in example_files[:3]:  # Limit to 3 examples
                content += f"#### {example_file.stem}\n\n"
                try:
                    example_content = example_file.read_text()
                    file_ext = example_file.suffix.lower()
                    lang = 'xml' if file_ext == '.xml' else 'yaml'
                    content += f"```{lang}\n{example_content}\n```\n\n"
                except Exception:
                    content += f"*Example file: {example_file.name}*\n\n"
        
        # Basic usage command
        extension_name = metadata.get('name', extension_path.name)
        content += "### Basic Usage\n\n"
        content += f"```bash\n"
        content += f"# Run with this extension\n"
        content += f"gsm run config.xml --extension={extension_name}\n\n"
        content += f"# List available commands for this extension\n"
        content += f"gsm {extension_name} --help\n"
        content += f"```\n\n"
        
        return DocumentationSection(
            title="Usage",
            content=content,
            level=2
        )
    
    def _generate_commands_section(self, extension_path: Path) -> DocumentationSection:
        """Generate commands section if extension provides CLI commands."""
        content = "Extension-specific commands provided by this extension.\n\n"
        
        # Try to find command definitions
        command_files = list(extension_path.glob('commands.py')) + \
                       list(extension_path.glob('cli.py'))
        
        if not command_files:
            content += "*This extension does not provide additional CLI commands.*\n\n"
        else:
            content += "Use `gsm --help` to see all available commands.\n\n"
        
        return DocumentationSection(
            title="Commands",
            content=content,
            level=2
        )
    
    def _generate_files_section(self, extension_path: Path) -> DocumentationSection:
        """Generate file structure documentation."""
        content = "Extension file structure:\n\n```\n"
        content += f"{extension_path.name}/\n"
        
        important_files = [
            'extension.json', 'config_schema.json', 'extension.py',
            'builder.py', 'runner.py', 'validator.py', 'commands.py',
            'requirements.txt', 'README.md'
        ]
        
        dirs_to_show = ['examples', 'templates', 'scripts']
        
        # Show important files
        for file_name in important_files:
            file_path = extension_path / file_name
            if file_path.exists():
                content += f"├── {file_name}\n"
        
        # Show important directories
        for dir_name in dirs_to_show:
            dir_path = extension_path / dir_name
            if dir_path.exists() and dir_path.is_dir():
                content += f"├── {dir_name}/\n"
                # Show first few files in directory
                files = list(dir_path.iterdir())[:3]
                for i, file in enumerate(files):
                    prefix = "└──" if i == len(files) - 1 else "├──"
                    content += f"│   {prefix} {file.name}\n"
        
        content += "```\n\n"
        
        return DocumentationSection(
            title="File Structure",
            content=content,
            level=2
        )


class DocumentationManager:
    """Manages documentation generation for multiple extensions."""
    
    def __init__(self, plugins_dir: Optional[Path] = None, output_dir: Optional[Path] = None):
        self.plugins_dir = plugins_dir or Path("plugins")
        self.output_dir = output_dir or Path("docs/extensions")
        self.generator = ExtensionDocumentationGenerator()
    
    def generate_all_documentation(self, formats: List[str] = None) -> Dict[str, Path]:
        """Generate documentation for all extensions."""
        formats = formats or ['markdown']
        generated_files = {}
        
        # Ensure output directory exists
        self.output_dir.mkdir(parents=True, exist_ok=True)
        
        # Find all extensions
        extension_dirs = [d for d in self.plugins_dir.iterdir() 
                         if d.is_dir() and not d.name.startswith('.')]
        
        for extension_dir in extension_dirs:
            try:
                doc = self.generator.generate_extension_documentation(extension_dir)
                
                for format_type in formats:
                    output_file = self._write_documentation(doc, format_type)
                    generated_files[f"{extension_dir.name}_{format_type}"] = output_file
                    
            except Exception as e:
                print(f"Warning: Failed to generate documentation for {extension_dir.name}: {e}")
                continue
        
        # Generate index file
        if generated_files:
            self._generate_index_file(extension_dirs, formats)
        
        return generated_files
    
    def _write_documentation(self, doc: ExtensionDocumentation, format_type: str) -> Path:
        """Write documentation to file in specified format."""
        if format_type == 'markdown':
            filename = f"{doc.name.lower().replace(' ', '_')}.md"
            output_file = self.output_dir / filename
            
            with open(output_file, 'w') as f:
                f.write(doc.to_markdown())
                
            return output_file
        
        else:
            raise ValueError(f"Unsupported format: {format_type}")
    
    def _generate_index_file(self, extension_dirs: List[Path], formats: List[str]):
        """Generate an index file listing all extensions."""
        index_content = "# GSM Extensions Documentation\n\n"
        index_content += f"Generated on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
        index_content += "## Available Extensions\n\n"
        
        for extension_dir in sorted(extension_dirs, key=lambda x: x.name):
            extension_name = extension_dir.name.replace('_', ' ').title()
            index_content += f"- [{extension_name}]({extension_dir.name.lower()}.md)\n"
        
        index_content += "\n## Usage\n\n"
        index_content += "Each extension provides specific functionality for GSM. "
        index_content += "Click on an extension name above to view its detailed documentation.\n\n"
        
        index_file = self.output_dir / "README.md"
        with open(index_file, 'w') as f:
            f.write(index_content)


def generate_documentation_for_extension(extension_path: Union[str, Path], 
                                        output_path: Optional[Union[str, Path]] = None,
                                        format_type: str = 'markdown') -> Path:
    """Convenience function to generate documentation for a single extension."""
    extension_path = Path(extension_path)
    
    if output_path is None:
        output_path = Path("docs/extensions") / f"{extension_path.name}.md"
    else:
        output_path = Path(output_path)
    
    generator = ExtensionDocumentationGenerator()
    doc = generator.generate_extension_documentation(extension_path, format_type)
    
    output_path.parent.mkdir(parents=True, exist_ok=True)
    
    if format_type == 'markdown':
        with open(output_path, 'w') as f:
            f.write(doc.to_markdown())
    
    return output_path


if __name__ == "__main__":
    import sys
    
    if len(sys.argv) < 2:
        print("Usage: python documentation_generator.py <extension_path> [output_path]")
        sys.exit(1)
    
    extension_path = Path(sys.argv[1])
    output_path = Path(sys.argv[2]) if len(sys.argv) > 2 else None
    
    try:
        result_path = generate_documentation_for_extension(extension_path, output_path)
        print(f"Documentation generated: {result_path}")
    except Exception as e:
        print(f"Error generating documentation: {e}")
        sys.exit(1)